home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
039a
/
d3d.zip
/
3DGR.C
next >
Wrap
Text File
|
1989-04-25
|
20KB
|
562 lines
/* 3DGR - 3D Graphic Subroutines for Turbo C
Written 8811.27 by Sir Mark Ewell Pendragon-Smythe, G.B.E.
This series of subroutines contains all the necessary pieces to develop
and display three-dimensional wire-frame objects. Because I could find
no readily available procedures to produce spheres or sections thereof,
I have written my own and included them here. Use of these procedures
requires no licensing or acknowledgement. I hope you find them helpful.
Comments may be addressed to
Sir Mark Ewell Pendragon-Smythe, G.B.E.
21 Strathallan Park
Suite 3
Rochester, NY 14607
Please do not send electronic mail as I rarely use CompuServe.
*/
#include <graphics.h>
#include <math.h>
#include <stdio.h>
double c[3][3]; /* Calculation Matrix */
double sc; /* Scaling Factor */
double degree = 3.141592654 / 180;
int xc; /* Screen x-centre */
int yc; /* Screen y-centre */
int xp; /* Plotable x coord */
int yp; /* Plotable y coord */
int zp; /* Computed z coord */
void set3d(double xrot, /* Roll */
double yrot, /* Pitch */
double zrot) /* Yaw */
/* Sets up 3D calculation matrices */
{
double rx,ry,rz;
rx=xrot*degree;
ry=yrot*degree;
rz=zrot*degree;
c[1][1]=cos(rx)*sc;
c[1][2]=cos(ry)*sc;
c[1][3]=cos(rz)*sc;
c[2][1]=sin(rx)*sc;
c[2][2]=sin(ry)*sc;
c[2][3]=sin(rz)*sc;
}
void calc3d(double aa, /* X coord (actual) */
double bb, /* Y coord (actual) */
double cc) /* Z coord (actual) */
/* Calculates a point in 3D given parametres in c[][] */
{
double xa,ya,za;
xa=c[1][3]*aa-c[2][3]*bb;
ya=c[2][3]*aa+c[1][3]*bb;
xp=c[1][1]*xa+c[2][1]*cc;
za=c[1][1]*cc-c[2][1]*xa;
yp=c[1][2]*ya-c[2][2]*za;
zp=c[2][2]*ya+c[1][2]*za;
}
void line3d(double x1,
double y1,
double z1,
double x2,
double y2,
double z2,
int box)
/* Generates a 3D line
box values 0 regular line
1 box in x1
2 box in y1
3 box in z1
4 box in x2
5 box in y2
6 box in z2*/
{
int xx,yy;
switch(box)
{
case 0 : {
calc3d(x1,y1,z1);
xx=xp;
yy=yp;
calc3d(x2,y2,z2);
line(xx+xc,yy+yc,xp+xc,yp+yc);
break;
}
case 1 : {
calc3d(x1,y1,z1);
xx=xp;
yy=yp;
calc3d(x1,y2,z1);
line(xx+xc,yy+yc,xp+xc,yp+yc);
moveto(xp+xc,yp+yc);
calc3d(x1,y2,z2);
lineto(xp+xc,yp+yc);
calc3d(x1,y1,z2);
lineto(xp+xc,yp+yc);
lineto(xx+xc,yy+yc);
break;
}
case 2 : {
calc3d(x1,y1,z1);
xx=xp;
yy=yp;
calc3d(x2,y1,z1);
line(xx+xc,yy+yc,xp+xc,yp+yc);
moveto(xp+xc,yp+yc);
calc3d(x2,y1,z2);
lineto(xp+xc,yp+yc);
calc3d(x1,y1,z2);
lineto(xp+xc,yp+yc);
lineto(xx+xc,yy+yc);
break;
}
case 3 : {
calc3d(x1,y1,z1);
xx=xp;
yy=yp;
calc3d(x2,y1,z1);
line(xx+xc,yy+yc,xp+xc,yp+yc);
moveto(xp+xc,yp+yc);
calc3d(x2,y2,z1);
lineto(xp+xc,yp+yc);
calc3d(x1,y2,z1);
lineto(xp+xc,yp+yc);
lineto(xx+xc,yy+yc);
break;
}
case 4 : {
calc3d(x2,y1,z1);
xx=xp;
yy=yp;
calc3d(x2,y2,z1);
line(xx+xc,yy+yc,xp+xc,yp+yc);
moveto(xp+xc,yp+yc);
calc3d(x2,y2,z2);
lineto(xp+xc,yp+yc);
calc3d(x2,y1,z2);
lineto(xp+xc,yp+yc);
lineto(xx+xc,yy+yc);
break;
}
case 5 : {
calc3d(x1,y2,z1);
xx=xp;
yy=yp;
calc3d(x2,y2,z1);
line(xx+xc,yy+yc,xp+xc,yp+yc);
moveto(xp+xc,yp+yc);
calc3d(x2,y2,z2);
lineto(xp+xc,yp+yc);
calc3d(x1,y2,z2);
lineto(xp+xc,yp+yc);
lineto(xx+xc,yy+yc);
break;
}
case 6 : {
calc3d(x1,y1,z2);
xx=xp;
yy=yp;
calc3d(x2,y1,z2);
line(xx+xc,yy+yc,xp+xc,yp+yc);
moveto(xp+xc,yp+yc);
calc3d(x2,y2,z2);
lineto(xp+xc,yp+yc);
calc3d(x1,y2,z2);
lineto(xp+xc,yp+yc);
lineto(xx+xc,yy+yc);
break;
}
}
}
void axis3d(double minx, /* First x coord */
double maxx, /* Second x coord */
double miny, /* First y coord */
double maxy, /* Second y coord */
double minz, /* First x coord */
double maxz) /* Second y coord */
/* Draws a series of axis lines */
{
calc3d(minx,0,0);
moveto(xp+xc,yp+yc);
calc3d(maxx,0,0);
lineto(xp+xc,yp+yc);
calc3d(0,miny,0);
moveto(xp+xc,yp+yc);
calc3d(0,maxy,0);
lineto(xp+xc,yp+yc);
calc3d(0,0,minz);
moveto(xp+xc,yp+yc);
calc3d(0,0,maxz);
lineto(xp+xc,yp+yc);
}
void arc3d(double xcentre, /* X centrepoint */
double ycentre, /* Y centrepoint */
double zcentre, /* Z centrepoint */
double starta, /* Starting angle */
double enda, /* Ending angle */
double incra, /* Angular increment */
double radius, /* Radius of arc */
int axis) /* Axis */
/* Draws an arc around the centre xcentre,ycentre,zcentre along axis points */
{
double cangle,cx,cy,cz;
cangle=starta;
while (cangle<=enda)
{
switch(axis)
{
case 1 : { /*X-Y Axis*/
cx=(radius*(cos(cangle*degree)));
cy=(radius*(sin(cangle*degree)));
cz=0;
break;
}
case 2 : { /*X-Z Axis*/
cx=(radius*(cos(cangle*degree)));
cy=0;
cz=(radius*(sin(cangle*degree)));
break;
}
case 3 : {
cx=0; /*Y-Z Axis*/
cy=(radius*(sin(cangle*degree)));
cz=(radius*(cos(cangle*degree)));
break;
}
}
calc3d(cx+xcentre,cy+ycentre,cz+zcentre);
if (cangle==starta) moveto(xp+xc,yp+yc); else lineto(xp+xc,yp+yc);
cangle+=+incra;
}
}
void meridian3d(double xcentre, /* X centrepoint */
double ycentre, /* Y centrepoint */
double zcentre, /* Z centrepoint */
double xrad, /* X arcs radius */
double yrad, /* Y arcs radius */
double zrad, /* Z arcs radius */
double starttheta, /* 1st parallel (in degrees) */
double finishtheta, /* Nth parallel (in degrees) */
double startphi, /* 1st meridian (in degrees) */
double finishphi, /* Nth meridian (in degrees) */
double increm) /* Angular increment */
/* Draws a series of meridians around xcentre,ycentre,zcentre
Practical values for theta are -90 thru 90
Practical values for phi are 0 thru 360
*/
{
double wx = (cos(startphi*degree)*xrad*cos(starttheta*degree))+xcentre;
double wy = (sin(startphi*degree)*yrad*cos(starttheta*degree))+ycentre;
double wz = (sin(startphi*degree)*zrad)+zcentre;
double a,a1;
calc3d(wx,wy,wz);
moveto(xp+xc,yp+yc);
for(a=startphi;a<=finishphi;a+=increm)
{
wx=(cos(a*degree)*xrad*cos(starttheta*degree))+xcentre;
wy=(sin(a*degree)*yrad*cos(starttheta*degree))+ycentre;
wz=(sin(starttheta*degree)*zrad)+zcentre;
calc3d(wx,wy,wz);
moveto(xp+xc,yp+yc);
for(a1=starttheta;a1<=finishtheta;a1+=increm)
{
wx=(cos(a*degree)*xrad*cos(a1*degree))+xcentre;
wy=(sin(a*degree)*yrad*cos(a1*degree))+ycentre;
wz=(sin(a1*degree)*zrad)+zcentre;
calc3d(wx,wy,wz);
lineto(xp+xc,yp+yc);
}
}
}
void parallel3d(double xcentre, /* X centrepoint */
double ycentre, /* Y centrepoint */
double zcentre, /* Z centrepoint */
double xrad, /* X arcs radius */
double yrad, /* Y arcs radius */
double zrad, /* Z arcs radius */
double starttheta, /* 1st parallel (in degrees) */
double finishtheta, /* Nth parallel (in degrees) */
double startphi, /* 1st meridian (in degrees) */
double finishphi, /* Nth meridian (in degrees) */
double increm) /* Angular increment */
/* Draws a series of parallels around xcentre, ycentre, zcentre
Practical values for theta are -90 thru 90
Practical values for phi are 0 thru 360
*/
{
double wx = (cos(startphi*degree)*xrad*cos(starttheta*degree))+xcentre;
double wy = (sin(startphi*degree)*yrad*cos(starttheta*degree))+ycentre;
double wz = (sin(startphi*degree)*zrad)+zcentre;
double a,a1;
calc3d(wx,wy,wz);
moveto(xp+xc,yp+yc);
for(a=starttheta;a<=finishtheta;a+=increm)
{
wx=(cos(startphi*degree)*xrad*cos(a*degree))+xcentre;
wy=(sin(startphi*degree)*yrad*cos(a*degree))+ycentre;
wz=(sin(a*degree)*zrad)+zcentre;
calc3d(wx,wy,wz);
moveto(xp+xc,yp+yc);
for(a1=startphi;a1<=finishphi;a1+=increm)
{
wx=(cos(a1*degree)*xrad*cos(a*degree))+xcentre;
wy=(sin(a1*degree)*yrad*cos(a*degree))+ycentre;
wz=(sin(a*degree)*zrad)+zcentre;
calc3d(wx,wy,wz);
lineto(xp+xc,yp+yc);
}
}
}
void globe3d(double xcentre, /* X centrepoint */
double ycentre, /* Y centrepoint */
double zcentre, /* Z centrepoint */
double xrad, /* X arcs radius */
double yrad, /* Y arcs radius */
double zrad, /* Z arcs radius */
double starttheta, /* 1st parallel (in degrees) */
double finishtheta, /* Nth parallel (in degrees) */
double startphi, /* 1st meridian (in degrees) */
double finishphi, /* Nth meridian (in degrees) */
double increm) /* Angular increment */
/* Draws a globe or section thereof by combining the meridian and parallel functions
Practical values for theta are -90 thru 90
Practical values for phi are 0 thru 360
*/
{
meridian3d(xcentre,ycentre,zcentre,xrad,yrad,zrad,starttheta,finishtheta,startphi,finishphi,increm);
parallel3d(xcentre,ycentre,zcentre,xrad,yrad,zrad,starttheta,finishtheta,startphi,finishphi,increm);
}
void spike3d(double xcentre, /* X centrepoint */
double ycentre, /* Y centrepoint */
double zcentre, /* Z centrepoint */
double xrad1, /* 1st x arcs radius */
double yrad1, /* 1st y arcs radius */
double zrad1, /* 1st z arcs radius */
double xrad2, /* 2nd x arcs radius */
double yrad2, /* 2nd y arcs radius */
double zrad2, /* 2nd z arcs radius */
double starttheta, /* 1st parallel (in degrees) */
double finishtheta, /* Nth parallel (in degrees) */
double startphi, /* 1st meridian (in degrees) */
double finishphi, /* Nth meridian (in degrees) */
double increm) /* Angular increment */
/* Draws lines between two angularly similar points with different radii
Practical values for theta are -90 thru 90
Practical values for phi are 0 thru 360
*/
{
double wx = (cos(startphi*degree)*xrad1*cos(starttheta*degree))+xcentre;
double wy = (sin(startphi*degree)*yrad1*cos(starttheta*degree))+ycentre;
double wz = (sin(startphi*degree)*zrad1)+zcentre;
double a,a1;
calc3d(wx,wy,wz);
moveto(xp+xc,yp+yc);
for(a=starttheta;a<=finishtheta;a+=increm)
{
wx=(cos(startphi*degree)*xrad1*cos(a*degree))+xcentre;
wy=(sin(startphi*degree)*yrad1*cos(a*degree))+ycentre;
wz=(sin(a*degree)*zrad1)+zcentre;
calc3d(wx,wy,wz);
moveto(xp+xc,yp+yc);
wx=(cos(startphi*degree)*xrad2*cos(a*degree))+xcentre;
wy=(sin(startphi*degree)*yrad2*cos(a*degree))+ycentre;
wz=(sin(a*degree)*zrad2)+zcentre;
calc3d(wx,wy,wz);
lineto(xp+xc,yp+yc);
for(a1=startphi;a1<=finishphi;a1+=increm)
{
wx=(cos(a1*degree)*xrad1*cos(a*degree))+xcentre;
wy=(sin(a1*degree)*yrad1*cos(a*degree))+ycentre;
wz=(sin(a*degree)*zrad1)+zcentre;
calc3d(wx,wy,wz);
moveto(xp+xc,yp+yc);
wx=(cos(a1*degree)*xrad2*cos(a*degree))+xcentre;
wy=(sin(a1*degree)*yrad2*cos(a*degree))+ycentre;
wz=(sin(a*degree)*zrad2)+zcentre;
calc3d(wx,wy,wz);
lineto(xp+xc,yp+yc);
}
}
}
void sector3d(double xcentre, /* X centrepoint */
double ycentre, /* Y centrepoint */
double zcentre, /* Z centrepoint */
double xrad1, /* 1st x arcs radius */
double yrad1, /* 1st y arcs radius */
double zrad1, /* 1st z arcs radius */
double xrad2, /* 2nd x arcs radius */
double yrad2, /* 2nd y arcs radius */
double zrad2, /* 2nd z arcs radius */
double starttheta, /* 1st parallel (in degrees) */
double finishtheta, /* Nth parallel (in degrees) */
double startphi, /* 1st meridian (in degrees) */
double finishphi, /* Nth meridian (In degrees) */
double increm) /* Angular increment */
/* Draws a "chunk" or sector of a sphere
Practical values for theta are -90 thru 90
Practical values for phi are 0 thru 360
*/
{
globe3d(xcentre,ycentre,zcentre,xrad1,yrad1,zrad1,starttheta,finishtheta,startphi,finishphi,increm);
globe3d(xcentre,ycentre,zcentre,xrad2,yrad2,zrad2,starttheta,finishtheta,startphi,finishphi,increm);
spike3d(xcentre,ycentre,zcentre,xrad1,yrad1,zrad1,xrad2,yrad2,zrad2,starttheta,finishtheta,startphi,finishphi,increm);
}
main()
/* This demonstration program may be deleted at user's discretion */
{
int graphdriver, graphmode, grapherror;
double a;
detectgraph(&graphdriver, &graphmode);
if(graphdriver < 0) printf("No graphics hardware detected\n");
initgraph(&graphdriver, &graphmode,"");
grapherror = graphresult();
if(grapherror < 0)
{
printf("Error: %s\n", grapherrormsg(grapherror));
exit(0);
}
cleardevice();
xc=getmaxx()/2; /* Initialize centre */
yc=getmaxy()/2;
sc=1.0; /* Set scale */
set3d(10,70,60); /* Set viewing angle */
/* line3d demo */
outtextxy(10,10,"Viewing angle 10 by 70 by 60");
outtextxy(10,20,"3D cube");
for(a=1;a<7;a++)
{
line3d(-50,-50,-50,50,50,50,a);
}
outtextxy(10,30,"Press [ENTER] to continue.");
getchar();
/* axis3d demo */
outtextxy(xc,10,"Viewing angle 10 by 70 by 60");
outtextxy(xc,20,"3D Axis");
axis3d(-100,100,-100,100,-100,100);
outtextxy(xc,30,"Press [ENTER] to continue.");
getchar();
/* arc3d demo */
outtextxy(10,50,"Viewing angle 10 by 70 by 60");
outtextxy(10,60,"3D Arcs");
for(a=1;a<4;a++)
{
arc3d(0,0,0,0,360,15,50,a);
}
outtextxy(10,70,"Press [ENTER] to continue.");
getchar();
/* meridian3d demo */
initgraph(&graphdriver, &graphmode,"");
cleardevice();
outtextxy(10,10,"Viewing angle 10 by 70 by 60");
outtextxy(10,20,"3D Meridian: Theta -90 to 90");
outtextxy(10,30," Phi 180 to 360");
meridian3d(0,0,0,75,75,75,-90,90,180,360,15);
outtextxy(10,40,"Press [ENTER] to continue.");
getchar();
/* parallel3d demo */
outtextxy(xc,10,"Viewing angle 10 by 70 by 60");
outtextxy(xc,20,"3D Parallel: Theta -90 to 90");
outtextxy(xc,30," Phi 0 to 180");
parallel3d(0,0,0,75,75,75,-90,90,0,180,15);
outtextxy(xc,40,"Press [ENTER] to continue.");
getchar();
/* globe3d demo */
initgraph(&graphdriver, &graphmode,"");
cleardevice();
outtextxy(10,10,"Viewing angle 10 by 70 by 60");
outtextxy(10,20,"3D Globe : Theta -90 to 90");
outtextxy(10,30," Phi 0 to 360");
globe3d(0,0,0,75,75,75,-90,90,0,360,15);
outtextxy(10,40,"Press [ENTER] to continue.");
getchar();
/* spike3d demo */
outtextxy(xc,10,"Viewing angle 10 by 70 by 60");
outtextxy(xc,20,"3D Spike : Theta -90 to 90");
outtextxy(xc,30," Phi 0 to 360");
spike3d(0,0,0,75,75,75,90,90,90,-90,90,0,360,15);
outtextxy(xc,40,"Press [ENTER] to continue.");
getchar();
/* sector3d demo */
initgraph(&graphdriver, &graphmode,"");
cleardevice();
outtextxy(10,10,"Viewing angle 10 by 70 by 60");
outtextxy(10,20,"3D Sector : Theta -90 to 90");
outtextxy(10,30," Phi 90 to 105");
sector3d(0,0,0,75,75,75,90,90,90,-90,90,90,105,15);
outtextxy(10,40,"Press [ENTER] to continue.");
getchar();
restorecrtmode();
}